/*
 * Copyright 2009 Jiwei Xu (http://www.xujiwei.com)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

provide("TinyJS.TinyView");

TinyView = Class({
    Initialize : function(arg) {
        var el = arg.Element;
        this.ViewElement = arg.Element;
        this.Document = arg.Document;

        this.offset = {
            X : el.offsetLeft,
            Y : el.offsetTop
        };
        this.__lastClickTick = 0;
        this.__dblClicked  = false;
        this.__lastX = 0;
        this.__lastY = 0;

        var THIS = this;

        var buildListener = function(func, fname) {
            ASSERT_VALID(func, "Invalid event '" + (fname || "") + "' listener");
            return function() {
                func.apply(THIS, arguments);
            };
        };

        // declare mouse messages
        declareMessage(el, {
            "mousedown" : buildListener(this.__OnMouseDown),

            "mousemove" : buildListener(this.__OnMouseMove),

            "mouseup"   : buildListener(this.__OnMouseUp)
        });

        // declare ui controls message
        var uiMsgs = arg.UIMessages;
        for (var i = 0; i < uiMsgs.length; ++i) {
            var obj = uiMsgs[i], id, msg, handle;
            id = obj.id || obj;
            if (id.indexOf(".") > -1) {
                id = p.substr(0, p.indexOf("."));
                msg = p.substr(p.indexOf(".") + 1);
            } else {
                msg = "click";
            }
            handle = "On" + id + msg.substr(0, 1).toUpperCase() + msg.substr(1);
            declareMessage(obj, msg, buildListener(this[handle], handle));
            if (this["OnUpdate" + id]) {
                declareMessage(obj, msg, buildListener(this["OnUpdate" + obj]));
            }
        }
    },

    ParseEvent : function(e) {
        var ret = {};
        for (var p in e) {
            ret[p] = e[p];
        }
        switch (e.type) {
            case "mousedown":
            case "mouseup":
            case "mousemove":
                ret.X = e.clientX - this.offset.X;
                ret.Y = e.clientY - this.offset.Y;
                ret.Button = e.button;
                break;
            default:
                break;
        }

        return ret;
    },

    __OnMouseDown : function(e) {
        switch (e.button) {
            case 0:
                this.OnLButtonDown(this.ParseEvent(e));
                break;
            case 1:
                break;
            case 2:
                this.OnRButtonDown(this.ParseEvent(e));
                break;
            default:
                break;
        }

        this.__dblClicked = false;

        if ((+new Date()) - this.__lastClickTick < 400 &&
                e.X == this.__lastX && e.Y == this.__lastY) {

            switch (e.button) {
                case 0:
                    this.OnLButtonDblClk(this.ParseEvent(e));
                    break;
                case 1:
                    break;
                case 2:
                    this.OnRButtonDblClk(this.ParseEvent(e));
                    break;
                default:
                    break;
            }

            this.__dblClicked = true;
        }

        this.__lastClickTick = +new Date();
        this.__lastX = e.X;
        this.__lastY = e.Y;
    },

    __OnMouseUp : function(e) {
        switch (e.button) {
            case 0:
                this.OnLButtonUp(this.ParseEvent(e));
                break;
            case 1:
                break;
            case 2:
                this.OnRButtonUp(this.ParseEvent(e));
                break;
            default:
                break;
        }

        if (!this.__dblClicked) {
            this.__dblClicked = false;
            switch (e.button) {
                case 0:
                    this.OnLButtonClick(this.ParseEvent(e));
                    break;
                case 1:
                    break;
                case 2:
                    this.OnRButtonClick(this.ParseEvent(e));
                    break;
                default:
                    break;
            }
        }
    },

    __OnMouseMove : function(e) {
        this.OnMouseMove(this.ParseEvent(e));
    },

    __OnMouseWheel : function(e) {
    },

    OnMouseMove : function() { },

    OnLButtonDown : function() { },

    OnLButtonUp : function() { },

    OnRButtonDown : function() { },

    OnRButtonUp : function() { },

    OnLButtonClick : function() { },

    OnLButtonDblClk : function() { },

    OnRButtonClick : function() { },

    OnRButtonDblClk : function() { },

    SetCursor : function(cursor) {
        this.Canvas.style.cursor = cursor;
    },

    ResetCursor : function() {
        this.Canvas.style.cursor = "default";
    },

    GetDocument : function() {
        return this.Document;
    },

    GetViewSize : function() {
        return {
            Width : this.ViewElement.width,
            Height : this.ViewElement.height
        };
    }
});